package model

import "strings"

/**
 * 数据库表结构
 * @author HuangXinBian
 */
type TableInfo struct {
	GsDbName           string       `json:"sDbName"`           //库名
	GsDbCodeName       string       `json:"sDbCodeName"`       //数据库在代码中的应用名(去除标识如'dev_'等库前缀)
	GsDbCodeSimplName  string       `json:"sDbCodeSimplName"`  //数据库在代码中的应用名(去除标识如'dev_'、'Bricks'等库前缀)
	GsName             string       `json:"sName"`             //表名
	GsEntityName       string       `json:"sEntityName"`       //实体表名
	GsLowerName        string       `json:"sLowerName"`        //全小写表名
	GsUpperName        string       `json:"sUpperName"`        //全大写表名
	GsObjName          string       `json:"sObjName"`          //头字母小写实体名
	GsUrl              string       `json:"sUrl"`              //表名对应的url地址
	GsComment          string       `json:"sComment"`          //表备注
	GiHasPid           int          `json:"iHasPid"`           //是否为含有上下级关系的表,默认-1
	GiHasPath          int          `json:"iHasPath"`          //是否含有路径字段
	GiHasOnlyignColumn int          `json:"iHasOnlyignColumn"` //是否含有'唯一'字段
	GiHasVersionColumn int          `json:"iHasVersionColumn"` //是否含有'iVersion'字段
	GiHasStateColumn   int          `json:"iHasStateColumn"`   //是否含有'iState'字段
	GsFieldKeyName     string       `json:"sFieldKeyName"`     //主键字段名称
	GsFieldKeyType     string       `json:"sFieldKeyType"`     //主键字段类型
	GcolumnInfoList    []ColumnInfo `json:"columnInfoList"`    //字段集合
	GkeyColumnList     []ColumnInfo `json:"keyColumnList"`     //主键字段集合
	GnotNullColumnList []ColumnInfo `json:"notNullColumnList"` //不允许为空字段集合
	GnullColumnList    []ColumnInfo `json:"nullColumnList"`    //允许为空字段集合
}

/**
 * 初始化对象
 */
func (this *TableInfo) SetDefault() {
	this.GiHasPid = -1
	this.GiHasPath = -1
	this.GiHasOnlyignColumn = -1
	this.GiHasVersionColumn = -1
	this.GiHasStateColumn = -1
	this.GcolumnInfoList = nil
	this.GkeyColumnList = nil
	this.GnotNullColumnList = nil
	this.GnullColumnList = nil
}

/**
 * 处理附属信息
 */
func (this *TableInfo) Supplementary() {
	this.HasPid()
	this.HasPath()
	this.HasOnlyignColumn()
	this.HasVersionColumn()
	this.HasStateColumn()
	this.GetsFieldKeyName()
	this.GetsFieldKeyType()

	this.SetsDbName(this.GsDbName)
}

/**
 * 设置 库名
 * @param sDbName 库名
 */
func (this *TableInfo) SetsDbName(sDbName string) {
	sDbName = strings.TrimSpace(sDbName)

	this.GsDbName = sDbName

	temp := sDbName

	this.GsDbCodeName = temp //默认数据库值

	iSt := strings.Index(strings.ToUpper(sDbName), "DEV_")
	if iSt == 0 {
		temp = string([]byte(sDbName)[len("DEV_"):])

		this.GsDbCodeName = temp //数据库在代码中的应用名(去除标识如'dev_'等库前缀)
	}

	if strings.Index(strings.ToUpper(temp), "BRICKS") == 0 {
		temp = string([]byte(temp)[len("BRICKS"):])
	} else if strings.Index(strings.ToUpper(temp), "PUZZLES") == 0 {
		temp = string([]byte(temp)[len("PUZZLES"):])
	}

	this.GsDbCodeSimplName = temp //数据库在代码中的应用名(去除标识如'dev_'、'Bricks'等库前缀)
}

/**
 * 设置 表名
 * @param sName 表名
 */
func (this *TableInfo) SetsName(sName string) {
	sName = strings.TrimSpace(sName)
	this.GsName = sName
	this.GsEntityName = hump(sName, false)
	this.GsObjName = hump(sName, true)
	this.GsLowerName = strings.ToLower(sName)
	this.GsUpperName = strings.ToUpper(sName)
	this.GsUrl = this.toUrl(sName)
}

/**
 * 设置 字段集合
 * @param columnInfoList 字段集合
 */
func (this *TableInfo) SetColumnInfoList(columnInfoList []ColumnInfo) {
	this.GcolumnInfoList = columnInfoList

	for _, columnInfo := range columnInfoList {
		if 1 == columnInfo.GiKey {
			this.GkeyColumnList = append(this.GkeyColumnList, columnInfo)
		}

		if 1 != columnInfo.GiNull {
			this.GnotNullColumnList = append(this.GnotNullColumnList, columnInfo)
		} else {
			this.GnullColumnList = append(this.GnullColumnList, columnInfo)
		}
	}
}

/**
 * 是否为含有上下级关系的表
 */
func (this *TableInfo) HasPid() int {
	if this.GiHasPid != -1 {
		return this.GiHasPid
	}

	if (this.GcolumnInfoList == nil) || (len(this.GcolumnInfoList) < 1) {
		return -1
	}

	for _, columnInfo := range this.GcolumnInfoList {
		if strings.Contains("sPId/sPid", columnInfo.GsField) {
			this.GiHasPid = 1
			return this.GiHasPid
		}
	}

	this.GiHasPid = 0

	return this.GiHasPid
}

/**
 * 是否含有路径字段
 * @return iHasPath 是否含有路径字段
 */
func (this *TableInfo) HasPath() int {
	if this.GiHasPath != -1 {
		return this.GiHasPath
	}

	if nil == this.GcolumnInfoList || len(this.GcolumnInfoList) < 1 {
		return -1
	}

	for _, columnInfo := range this.GcolumnInfoList {
		if strings.Contains("sPath", columnInfo.GsField) {
			this.GiHasPath = 1
			return this.GiHasPath
		}
	}

	this.GiHasPath = 0

	return this.GiHasPath
}

/**
 * 是否含有'唯一'字段
 * @return iHasOnlyignColumn 是否含有'唯一'字段
 */
func (this *TableInfo) HasOnlyignColumn() int {
	if this.GiHasOnlyignColumn != -1 {
		return this.GiHasOnlyignColumn
	}

	if nil == this.GcolumnInfoList || len(this.GcolumnInfoList) < 1 {
		return -1
	}

	for _, columnInfo := range this.GcolumnInfoList {
		if strings.Contains("sOnlyign", columnInfo.GsField) {
			this.GiHasOnlyignColumn = 1
			return this.GiHasOnlyignColumn
		}
	}

	this.GiHasOnlyignColumn = 0

	return this.GiHasOnlyignColumn
}

/**
 * 是否含有'iVersion'字段
 * @return iHasVersionColumn 是否含有'iVersion'字段
 */
func (this *TableInfo) HasVersionColumn() int {
	if this.GiHasVersionColumn != -1 {
		return this.GiHasVersionColumn
	}

	if (nil == this.GcolumnInfoList) || (len(this.GcolumnInfoList) < 1) {
		return -1
	}

	for _, columnInfo := range this.GcolumnInfoList {
		if strings.Contains("iVersion", columnInfo.GsField) {
			this.GiHasVersionColumn = 1
			return this.GiHasVersionColumn
		}
	}

	this.GiHasVersionColumn = 0

	return this.GiHasVersionColumn
}

/**
 * 是否含有'iState'字段
 * @return iHasStateColumn 是否含有'iState'字段
 */
func (this *TableInfo) HasStateColumn() int {
	if this.GiHasStateColumn != -1 {
		return this.GiHasStateColumn
	}

	if (nil == this.GcolumnInfoList) || (len(this.GcolumnInfoList) < 1) {
		return -1
	}

	for _, columnInfo := range this.GcolumnInfoList {
		if strings.Contains("iState", columnInfo.GsField) {
			this.GiHasStateColumn = 1
			return this.GiHasStateColumn
		}
	}

	this.GiHasStateColumn = 0

	return this.GiHasStateColumn
}

/**
 * 获得 主键字段名称
 * @return sFieldKeyName 主键字段名称
 */
func (this *TableInfo) GetsFieldKeyName() string {
	if this.GsFieldKeyName != "" {
		return this.GsFieldKeyName
	}

	if (nil == this.GcolumnInfoList) || (len(this.GcolumnInfoList) < 1) {
		return ""
	}

	for _, columnInfo := range this.GcolumnInfoList {
		if columnInfo.GiKey == 1 {
			this.GsFieldKeyName = columnInfo.GsField
			return this.GsFieldKeyName
		}
	}

	return this.GsFieldKeyName
}

/**
 * 获得 主键字段类型
 * @return sFieldKeyType 主键字段类型
 */
func (this *TableInfo) GetsFieldKeyType() string {
	if this.GsFieldKeyType != "" {
		return this.GsFieldKeyType
	}

	if (nil == this.GcolumnInfoList) || (len(this.GcolumnInfoList) < 1) {
		return ""
	}

	for _, columnInfo := range this.GcolumnInfoList {
		if columnInfo.GiKey == 1 {
			this.GsFieldKeyType = columnInfo.GsTypeByJava
			return this.GsFieldKeyType
		}
	}

	return this.GsFieldKeyType
}

/**
* 创建url字符串
* @param str 字符串
* @return
 */
func (this *TableInfo) toUrl(str string) string {
	str = strings.TrimSpace(str)
	if "" == str {
		return ""
	}

	if (str == strings.ToLower(str)) && !strings.Contains(str, "_") { //不含下划线而且全小写则直接做为路径
		return this.toUrlDefend(str)
	}

	if (str == strings.ToUpper(str)) && !strings.Contains(str, "_") { //不含下划线而且全大写则转小写后直接做为路径
		return this.toUrlDefend(strings.ToLower(str))
	}

	if (str == strings.ToLower(str)) && strings.Contains(str, "_") { //含下划线而且全小写则把下划线转换后直接做为路径
		return this.toUrlDefend(strings.Replace(str, "_", "/", -1))
	}

	if (str == strings.ToUpper(str)) && strings.Contains(str, "_") { //含下划线而且全大写则转小写后把下划线转换后直接做为路径
		return this.toUrlDefend(strings.Replace(strings.ToLower(str), "_", "/", -1))
	}

	if strings.Contains(str, "_") { //含下划线而且全大写则转小写后把下划线转换后直接做为路径 //这个是预防,先按这个方式处理
		return this.toUrlDefend(strings.Replace(strings.ToLower(str), "_", "/", -1))
	}

	var build strings.Builder
	for _, ch := range str {
		if 64 < ch && ch < 91 { //大写
			build.WriteString("/")
			build.WriteString(strings.ToLower(string(ch)))
			continue
		}

		build.WriteString(string(ch))
	}

	return this.toUrlDefend(build.String())
}

/**
* 预防url字符串
* @param str 字符串
* @return
 */
func (this *TableInfo) toUrlDefend(str string) string {
	if "" == str {
		return str
	}

	result := strings.Replace(str, " ", "", -1)

	if !strings.HasPrefix(result, "/") {
		result = "/" + result
	}

	if !strings.HasSuffix(result, "/") { // 以'/'结尾
		result = result[0 : len(result)-1]
	}

	result = strings.Replace(str, "//", "/", -1)

	return result
}
